/*
    This file is part of tPortal.

    tPortal is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    tPortal is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with tPortal.  If not, see <http://www.gnu.org/licenses/>.

    The original code was written by Sebastien Bettinger <sebastien.bettinger@gmail.com>

 */

package net.tinyportal.portal;

import java.util.ArrayList;
import java.util.List;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletMode;
import javax.portlet.PortletModeException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.WindowState;
import javax.portlet.WindowStateException;

import net.tinyportal.Constant;
import net.tinyportal.javax.portlet.TpActionResponse;
import net.tinyportal.javax.portlet.TpPortletConfig;
import net.tinyportal.javax.portlet.TpPortletPreference;
import net.tinyportal.service.PortletService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

/**
 * Bean reprÃ©sentant simplement le contenu d'un portlet.<br/>
 * Chaque instance de portlet est emballÃ© par son propre PortletHolder.
 * Celui-ci permet de gÃ©rer le cycle de vie d'un portlet, ses changements d'Ã©tats
 * ainsi que son titre et son contenu
 * 
 * @author seb0uil@gmail.com
 *
 */
public class PortletHolder implements Cloneable {

	/**
	 * Titre du portlet
	 */
	private String Title = null;

	/**
	 * Contenu html du portlet
	 */
	private StringBuffer Content = new StringBuffer();

	/**
	 * Etat windowState du portlet
	 */
	private WindowState windowState = WindowState.NORMAL;

	/**
	 * Mode (VIEW, EDIT, HELP) du portlet
	 */
	private PortletMode portletMode = PortletMode.VIEW;


	private RenderRequest renderRequest;
	private RenderResponse renderResponse;
	private TpPortletConfig portletConfig;
	private TpActionResponse actionResponse;
	private TpPortletPreference preferences;

	/**
	 * Nom du portlet
	 */
	private String portletName;

	/**
	 * Id unique du portlet
	 */
	private String portletId;

	/**
	 * Portlet JSR gÃ©rÃ© par ce holder
	 */
	GenericPortlet portlet;

	/**
	 * Liste des types Mime supportÃ©s par le portlet
	 */
	private List<String> MimeType = new ArrayList<String>();
	
	@Autowired
	private PortletService portletService;
	
	@Autowired
	ApplicationContext applicationContext;


	public PortletHolder(PortletHolder bean) {
		portletConfig = bean.getPortletConfig();
		TpPortletPreference preferences = portletConfig.getPortletPreference().clone();
		this.preferences = preferences;

		this.Title = new String();
		if (bean.Title != null) this.Title = new String(bean.Title);
		this.portletName = new String(bean.portletName);
		this.MimeType = bean.MimeType;

		this.portlet = bean.getPortlet();
		setPortletId(this);	
	}

	public PortletHolder(GenericPortlet portlet) {
		TpPortletConfig portletConfig = ((TpPortletConfig)portlet.getPortletConfig());
		this.portletConfig = portletConfig;
		TpPortletPreference preferences = portletConfig.getPortletPreference().clone();
		this.preferences = preferences;

		this.Title = portletConfig.getPortletName();
		this.portletName = portletConfig.getPortletName();
		this.MimeType = portletConfig.getMimeType();

		setPortletId(this);
		this.portlet = portlet;
	}

	/*
	 * Gestion de l'Ã©tat fenÃªtrÃ© du portlet
	 */

	/**
	 * Retourne l'Ã©tat du portlet
	 */
	public WindowState getWindowState() {
		return windowState;
	}

	/**
	 * Positionne un Ã©tat pour l'instance du portlet
	 * @param windowState Etat Ã  positionner
	 * @throws WindowStateException Dans le cas ou l'Ã©tat n'est pas autorisÃ© (par
	 * le portlet ou le portail) une PortletModeException est levÃ©e
	 */
	public void setWindowState(WindowState windowState) throws WindowStateException {
		if (!isWindowStateAllowed(windowState))
			throw new WindowStateException(windowState + " not allowed",windowState);
		if (!Constant.portal_context.isWindowStateAllowed(windowState))
			throw new WindowStateException(windowState + " not allowed by portal",windowState);
		this.windowState = windowState;
	}

	/**
	 * DÃ©termine si l'Ã©tat passÃ© en paramÃ¨tre est autorisÃ© pour le portlet
	 * @param Ã©tat Ã  tester
	 * @return vrai si l'Ã©tat est autorisÃ©
	 */
	public boolean isWindowStateAllowed(String state) {
		return isWindowStateAllowed(new WindowState(state));
	}

	/**
	 * DÃ©termine si l'Ã©tat passÃ© en paramÃ¨tre est autorisÃ© pour le portlet
	 * @param Ã©tat Ã  tester
	 * @return vrai si l'Ã©tat est autorisÃ©
	 */
	public boolean isWindowStateAllowed(WindowState state) {
		List<WindowState> windowStates = portletConfig.getWindowsStates();
		return windowStates.contains(state);
	}

	/*
	 * Gestion du mode du portlet
	 */

	/**
	 * Retourne le mode en cours pour l'instance du portlet
	 */
	public PortletMode getPortletMode() {
		return portletMode;
	}

	/**
	 * Positionne un mode (VIEW, EDIT, HELP) pour l'instance du portlet
	 * @param portletMode mode Ã  positionner
	 * @throws PortletModeException Dans le cas ou le mode n'est pas autorisÃ© (par
	 * le portlet ou le portail) une PortletModeException est levÃ©e
	 */
	public void setPortletMode(PortletMode portletMode) throws PortletModeException {
		if (!isPortletModeAllowed(portletMode))
			throw new PortletModeException(portletMode + " not allowed",portletMode);
		if (!Constant.portal_context.isPortletModeAllowed(portletMode))
			throw new PortletModeException(portletMode + " not allowed by portal",portletMode);
		this.portletMode = portletMode;
	}

	/**
	 * DÃ©termine si le mode passÃ© en paramÃ¨tre est autorisÃ© pour le portlet
	 * @param mode Ã  tester
	 * @return vrai si le mode est autorisÃ©
	 */
	public boolean isPortletModeAllowed(String mode) {
		return isPortletModeAllowed(new PortletMode(mode));
	}

	/**
	 * DÃ©termine si le mode passÃ© en paramÃ¨tre est autorisÃ© pour le portlet
	 * @param mode Ã  tester
	 * @return vrai si le mode est autorisÃ©
	 */
	public boolean isPortletModeAllowed(PortletMode mode) {
		List<PortletMode> portletMode = portletConfig.getPortletModes();
		return portletMode.contains(mode);	
	}

	/*
	 * Getter && Setter
	 */
	public RenderRequest getRenderRequest() {
		return renderRequest;
	}

	public void setRenderRequest(RenderRequest renderRequest) {
		this.renderRequest = renderRequest;
	}

	public RenderResponse getRenderResponse() {
		return renderResponse;
	}

	public void setRenderResponse(RenderResponse renderResponse) {
		this.renderResponse = renderResponse;
	}

	public TpPortletConfig getPortletConfig() {
		return portletConfig;
	}

	public void setPortletName(String portletName) {
		this.portletName = portletName;
	}

	public String getPortletName() {
		return portletName;
	}

	public String getPortletId() {
		return portletId;
	}

	public void setPortletId(Object o) {
		this.portletId = o.toString().split("@")[1];
	}

	public void setPortletId(String portletId) {
		this.portletId = portletId;
	}

	public TpActionResponse getActionResponse() {
		return actionResponse;
	}

	public void setActionResponse(TpActionResponse actionResponse) {
		this.actionResponse = actionResponse;
	}

	public List<String> getMimeType() {
		return MimeType;
	}

	public void setMimeType(List<String> mimeType) {
		MimeType = mimeType;
	}

	public GenericPortlet getPortlet() {
		return portlet;
	}

	public void setPortlet(GenericPortlet portlet) {
		this.portlet = portlet;
	}

	public String getTitle() {
		return Title;
	}
	public void setTitle(String title) {
		Title = title;
	}
	public String getContent() {
		return Content.toString();
	}
	public void setContent(String content) {
		Content = new StringBuffer(content);
	}

	public void addContent(String content) {
		Content.append(content);
	}

	public TpPortletPreference getPreferences() {
		return preferences;
	}

	public void setPreferences(TpPortletPreference preferences) {
		this.preferences = preferences;
	}

	/**
	 * 
	 */
	public PortletHolder clone() {
		PortletHolder o = null;
		try {
			// On rÃ©cupÃ¨re l'instance Ã  renvoyer par l'appel de la 
			// mÃ©thode super.clone()
			o = (PortletHolder) super.clone();
			o.setPortletId(this.portletId);
			o.setContent(this.getContent());

//			TpPortletPreference preferences =  portletService.getPreferenceForPortletId(portletId);//this.preferences.clone();
			o.setPreferences(preferences);
			o.setMimeType(MimeType);
			
			o.setPortletMode(getPortletMode());
			o.setPortlet(this.getPortlet());

		} catch(CloneNotSupportedException cnse) {
			// Ne devrait jamais arriver car nous implÃ©mentons 
			// l'interface Cloneable
			cnse.printStackTrace(System.err);
		} catch (PortletModeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// on renvoie le clone
		return o;
	}
}
